/*
创建函数
1、 先开一个新的内存空间（浏览器为其分配一个十六进制的地址）（和给普通对象开辟的空间一样）
2、把函数体中编写的js代码当做字符串存储到空间中
（函数只创建不执行没有意义）(和普通对象相比，普通对象存储的是有意义的键值对（能通过.x找到对应的键值），函数存储的是无意义的字符串)
3、 把分配的地址赋值给声明的函数名
*/


function fn() {
    var ary = Array.prototype.slice.call(arguments); //类数组不能用数组里的方法,故这里用了Array.prototype.slice.call
    return eval(ary.join('+'));
}

let sum = fn(12,23,34,45,56);
console.log(sum);

/*
执行函数
目的：执行函数体中的代码
1、 函数执行的时候（每一次执行），浏览器会形成一个新的私有作用域（【只能】执行函数体中的代码），供函数体中的代码执行。
2、执行代码之前，先把创建函数存储的那些字符串变为真正的js表达式，按照从上到下顺序在私有作用域中执行(具体执行过程参见下面)


同一个函数两次执行之间没有直接关系
↓
 函数每次执行都会形成一个新的私有作用域，每次都是把存在内存中的函数体字符串copy一部分出来执行。两次之间没有直接关系但可能存在间接关系（比如说在全局下有个变量，你在函数内用到了）。


 闭包
 ↓
 形成的私有作用域会把函数体中的私有变量都包裹起来（保护起来），在私有作用域中操作私有变量和外界没关系，外界也无法直接的操作私有变量，我们把函数自执行形成的这种保护机制叫做闭包。


 函数执行形成一个全新独立的私有的作用域
1、 形参赋值
2、 变量提升
3、 代码自上而下执行
4、 当前栈内存（私有作用域）销毁或则不销毁

构造函数执行参见 oop/05构造函数设计模式
*/


// ↓不会报错 因为函数并没有执行 这里函数只执行了创建函数的步骤(故只把函数体copy到了开辟的堆内存中，没有验证) 而没有进行执行函数的步骤
function abc(){
    x(123);
}
